#
# Makefile for xboot
# Create by: Jianjun Jiang <8192542@qq.com>
#

#
# You must pass CROSS_COMPILE and PLATFORM variable.
#
CROSS_COMPILE	?= arm-linux-gnueabihf-
PLATFORM		?= arm32-x3288

#
# Get platform information about ARCH and MACH from PLATFORM variable.
#
ifeq ($(words $(subst -, , $(PLATFORM))), 2)
ARCH		:= $(word 1, $(subst -, , $(PLATFORM)))
MACH		:= mach-$(word 2, $(subst -, , $(PLATFORM)))
else
ARCH		:= x64
MACH		:= mach-sandbox
endif

#
# System environment variable.
#
ifneq (,$(findstring Linux, $(shell uname -s)))
HOSTOS		:= linux
else
HOSTOS		:= windows
endif

#
# Load default variables.
#
ASFLAGS		:= -g -ggdb -Wall -O0
CFLAGS		:= -g -ggdb -Wall -O0
CXXFLAGS	:= -g -ggdb -Wall -O0
LDFLAGS		:= -T arch/$(ARCH)/$(MACH)/xboot.ld -nostdlib
MCFLAGS		:=

LIBDIRS		:=
LIBS 		:=
INCDIRS		:=
SRCDIRS		:=

#
# Override default variables.
#
sinclude arch/$(ARCH)/$(MACH)/xboot.mk

#
# Modify default variables.
#
ifeq ($(strip $(ARCH)), arm32)
DEFINES		+=	-D__ARM32__
endif
ifeq ($(strip $(ARCH)), arm64)
DEFINES		+=	-D__ARM64__
endif
ifeq ($(strip $(ARCH)), x64)
DEFINES		+=	-D__X64__
endif

ASFLAGS		+= 	-ffreestanding -std=gnu99 $(DEFINES)
CFLAGS		+=	-ffreestanding -std=gnu99 $(DEFINES)
CXXFLAGS	+=	-ffreestanding -std=gnu99 $(DEFINES)

#
# Add necessary directory for INCDIRS and SRCDIRS.
#
INCDIRS		+=	include										\
				arch/$(ARCH)/include						\
				arch/$(ARCH)/$(MACH)/include

SRCDIRS		+=	arch/$(ARCH)/lib/cpu						\
				arch/$(ARCH)/lib							\
				arch/$(ARCH)/$(MACH)						\
				arch/$(ARCH)/$(MACH)/driver					\
				lib/libc									\
				lib/libc/charset							\
				lib/libc/crypto								\
				lib/libc/ctype								\
				lib/libc/environ							\
				lib/libc/errno								\
				lib/libc/exit								\
				lib/libc/filter								\
				lib/libc/locale								\
				lib/libc/malloc								\
				lib/libc/stdio								\
				lib/libc/stdlib								\
				lib/libc/string								\
				lib/libc/time								\
				lib/libm/$(ARCH)							\
				lib/libm									\
				lib/libx									\
				lib/xfs										\
				init										\
				kernel										\
				kernel/core									\
				kernel/shell								\
				kernel/command								\
				kernel/time									\
				kernel/fs									\
				kernel/fs/vfs								\
				kernel/fs/ramfs								\
				kernel/fs/sysfs								\
				kernel/fs/arfs								\
				kernel/fs/tarfs								\
				kernel/fs/cpiofs							\
				kernel/fs/fatfs								\
				driver/adc									\
				driver/audio								\
				driver/battery								\
				driver/block								\
				driver/block/partition						\
				driver/block/romdisk						\
				driver/buzzer								\
				driver/clk									\
				driver/clockevent							\
				driver/clocksource							\
				driver/console								\
				driver/dac									\
				driver/dma									\
				driver/fb									\
				driver/fb/sw								\
				driver/gpio									\
				driver/i2c									\
				driver/input								\
				driver/input/rc								\
				driver/interrupt							\
				driver/led									\
				driver/mmc									\
				driver/pwm									\
				driver/regulator							\
				driver/rng									\
				driver/rtc									\
				driver/spi									\
				driver/uart									\
				driver/vibrator								\
				driver/watchdog

#
# Add external library
#
INCDIRS		+= 	external/json-parser-1.1.0
SRCDIRS		+=	external/json-parser-1.1.0

INCDIRS		+= 	external/zlib-1.2.8
SRCDIRS		+=	external/zlib-1.2.8

INCDIRS		+= 	external/libpng-1.5.14
SRCDIRS		+=	external/libpng-1.5.14

INCDIRS		+= 	external/pixman-0.32.8 \
				external/pixman-0.32.8/$(ARCH)
SRCDIRS		+=	external/pixman-0.32.8 \
				external/pixman-0.32.8/$(ARCH)

INCDIRS		+= 	external/cairo-1.14.2
SRCDIRS		+=	external/cairo-1.14.2

INCDIRS		+= 	external/freetype-2.4.11/include \
				external/freetype-2.4.11/src/base \
				external/freetype-2.4.11/src/raster	\
				external/freetype-2.4.11/src/smooth	\
				external/freetype-2.4.11/src/cff \
				external/freetype-2.4.11/src/cid \
				external/freetype-2.4.11/src/pfr \
				external/freetype-2.4.11/src/sfnt \
				external/freetype-2.4.11/src/truetype \
				external/freetype-2.4.11/src/type1 \
				external/freetype-2.4.11/src/type42 \
				external/freetype-2.4.11/src/winfonts \
				external/freetype-2.4.11/src/autofit \
				external/freetype-2.4.11/src/cache \
				external/freetype-2.4.11/src/gxvalid \
				external/freetype-2.4.11/src/otvalid \
				external/freetype-2.4.11/src/psaux \
				external/freetype-2.4.11/src/pshinter \
				external/freetype-2.4.11/src/psnames
SRCDIRS		+=	external/freetype-2.4.11/src/base \
				external/freetype-2.4.11/src/raster \
				external/freetype-2.4.11/src/smooth \
				external/freetype-2.4.11/src/cff \
				external/freetype-2.4.11/src/cid \
				external/freetype-2.4.11/src/pfr \
				external/freetype-2.4.11/src/sfnt \
				external/freetype-2.4.11/src/truetype \
				external/freetype-2.4.11/src/type1 \
				external/freetype-2.4.11/src/type42 \
				external/freetype-2.4.11/src/winfonts \
				external/freetype-2.4.11/src/autofit \
				external/freetype-2.4.11/src/cache \
				external/freetype-2.4.11/src/gxvalid \
				external/freetype-2.4.11/src/otvalid \
				external/freetype-2.4.11/src/psaux \
				external/freetype-2.4.11/src/pshinter \
				external/freetype-2.4.11/src/psnames

#
# You shouldn't need to change anything below this point.
#
AS			:=	$(CROSS_COMPILE)gcc -x assembler-with-cpp
CC			:=	$(CROSS_COMPILE)gcc
CXX			:=	$(CROSS_COMPILE)g++
LD			:=	$(CROSS_COMPILE)ld
AR			:=	$(CROSS_COMPILE)ar
OC			:=	$(CROSS_COMPILE)objcopy
OD			:=	$(CROSS_COMPILE)objdump
MKDIR		:=	mkdir -p
CP			:=	cp -af
RM			:=	rm -fr
CD			:=	cd
FIND		:=	find
CPIO		:=	cpio -o -H newc --quiet

#
# Xboot variables
#
X_ASFLAGS	:=	$(MCFLAGS) $(ASFLAGS)
X_CFLAGS	:=	$(MCFLAGS) $(CFLAGS)
X_CXXFLAGS	:=	$(MCFLAGS) $(CXXFLAGS)
X_LDFLAGS	:=	$(LDFLAGS)
X_LIBS		:=	$(LIBS) -lgcc

X_OUT		:=	output
X_NAME		:=	$(patsubst %, $(X_OUT)/%, lcdscreen)
X_INCDIRS	:=	$(patsubst %, -I %, $(INCDIRS))
X_LIBDIRS	:=	$(patsubst %, -L %, $(LIBDIRS))
X_SRCDIRS	:=	$(patsubst %, %, $(SRCDIRS))
X_OBJDIRS	:=	$(patsubst %, .obj/%, $(X_SRCDIRS))

X_SFILES	:=	$(foreach dir, $(X_SRCDIRS), $(wildcard $(dir)/*.S))
X_CFILES	:=	$(foreach dir, $(X_SRCDIRS), $(wildcard $(dir)/*.c))
X_CPPFILES	:=	$(foreach dir, $(X_SRCDIRS), $(wildcard $(dir)/*.cpp))

X_SDEPS		:=	$(patsubst %, .obj/%, $(X_SFILES:.S=.o.d))
X_CDEPS		:=	$(patsubst %, .obj/%, $(X_CFILES:.c=.o.d))
X_CPPDEPS	:=	$(patsubst %, .obj/%, $(X_CPPFILES:.cpp=.o.d))
X_DEPS		:=	$(X_SDEPS) $(X_CDEPS) $(X_CPPDEPS)

X_SOBJS		:=	$(patsubst %, .obj/%, $(X_SFILES:.S=.o))
X_COBJS		:=	$(patsubst %, .obj/%, $(X_CFILES:.c=.o))
X_CPPOBJS	:=	$(patsubst %, .obj/%, $(X_CPPFILES:.cpp=.o)) 
X_OBJS		:=	$(X_SOBJS) $(X_COBJS) $(X_CPPOBJS)

VPATH		:=	$(X_OBJDIRS) $(M_OBJDIRS)
.PHONY:	all clean xbegin xend xclean

#
# Xboot rules
#
all : xbegin $(X_NAME) xend

$(X_NAME) : $(X_OBJS)
	@echo [LD] Linking $@
	@$(CC) $(X_LDFLAGS) $(X_LIBDIRS) -Wl,--cref,-Map=$@.map $^ -o $@ $(X_LIBS)
	@echo [OC] Objcopying $@.bin
	@$(OC) -v -O binary $@ $@.bin

$(X_SOBJS) : .obj/%.o : %.S
	@echo [AS] $<
	@$(AS) $(X_ASFLAGS) $(X_INCDIRS) -c $< -o $@
	@$(AS) $(X_ASFLAGS) -MD -MP -MF $@.d $(X_INCDIRS) -c $< -o $@

$(X_COBJS) : .obj/%.o : %.c
	@echo [CC] $<
	@$(CC) $(X_CFLAGS) $(X_INCDIRS) -c $< -o $@
	@$(CC) $(X_CFLAGS) -MD -MP -MF $@.d $(X_INCDIRS) -c $< -o $@

$(X_CPPOBJS) : .obj/%.o : %.cpp
	@echo [CXX] $<
	@$(CXX) $(X_CXXFLAGS) $(X_INCDIRS) -c $< -o $@	
	@$(CXX) $(X_CXXFLAGS) -MD -MP -MF $@.d $(X_INCDIRS) -c $< -o $@

clean: xclean
	@$(RM) $(X_OBJDIRS) $(X_OUT)
	@echo Clean xboot complete.

#
# Include the dependency files, should be place the last of makefile
#
sinclude $(shell $(MKDIR) $(X_OBJDIRS) $(X_OUT)						\
			&& $(RM) .obj/romdisk									\
			&& $(RM) .obj/romdisk.cpio								\
			&& $(RM) .obj/init/version.o							\
			&& $(RM) .obj/driver/block/romdisk/data.o				\
			&& $(CP) romdisk .obj									\
			&& $(CP) arch/$(ARCH)/$(MACH)/romdisk .obj				\
			&& $(CD) .obj/romdisk									\
			&& $(FIND) . -not -name . | $(CPIO) > ../romdisk.cpio	\
			&& $(CD) ../..)											\
			$(X_DEPS) $(M_DEPS)
